﻿using System.Data;
using System.Linq;
using System.Transactions;
using CodeCamp.BL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using CodeCamp.BL.Model;
using System.Collections.Generic;
using System.Web;

namespace CodeCamp.Tests
{


	/// <summary>
	///This is a test class for CodeCampBLTest and is intended
	///to contain all CodeCampBLTest Unit Tests
	///</summary>
	[TestClass()]
	public class CodeCampBLTest
	{

		/// <summary>
		///A test for AddInterest
		///</summary>
		[TestMethod()]
		public void AddInterest_BunkSessionID_RunsSilently()
		{
			Guid userId = new Guid("c6097fb6-ada7-4cc0-816f-47788918b7e6");
			int sessionID = -70;
			CodeCampBL.AddInterest(userId, sessionID);
			// Assert - no exception.
		}


		[TestMethod()]
		[ExpectedException(typeof(UpdateException))]
		public void AddInterest_BunkUserID_Throws()
		{
			Guid userId = Guid.NewGuid();
			var preSession = CodeCampBL.ListSessions().First();
			CodeCampBL.AddInterest(userId, preSession.Session.SessionID);
			var postSession = CodeCampBL.ListSessions().First();
		}


		[TestMethod()]
		public void AddInterest_ValidData_Updates()
		{
			using (var tran = new TransactionScope())
			{
				Guid userId = new Guid("c6097fb6-ada7-4cc0-816f-47788918b7e6");
				var preSession = CodeCampBL.ListSessions().First();
				CodeCampBL.AddInterest(userId, preSession.Session.SessionID);
				var postSession = CodeCampBL.GetSession(preSession.Session.SessionID);
			}
		}

		/// <summary>
		///A test for ListSessionsDetail
		///</summary>
		[TestMethod()]
		public void ListSessions_CountsInterest()
		{
			IEnumerable<SessionDetail> actual;
			actual = CodeCampBL.ListSessions();
			Assert.IsNotNull(actual);
			Assert.IsTrue(actual.Any(sd => sd.Interest > 0));
		}

		[TestMethod()]
		public void AddPresenter_CoPresenterNotFound_ReturnsFalse()
		{
			using (TransactionScope tran = new TransactionScope())
			{
				int sessionID = 1;
				string coPresenterEmail = "bunk!#@#$%$^%";
				bool actual = CodeCampBL.AddPresenter(sessionID, coPresenterEmail);
				Assert.IsFalse(actual);
			}
		}

		[TestMethod()]
		public void AddPresenter_ValidCoPresenterValidSession_ReturnsTrue()
		{
			string coPresenterEmail;
			int sessionID;
			using (var context = new CodeCampEntities())
			{
				coPresenterEmail = context.aspnet_Membership.First().Email;
				sessionID = context.Sessions.First().SessionID;
			}

			using (TransactionScope tran = new TransactionScope())
			{
				bool actual = CodeCampBL.AddPresenter(sessionID, coPresenterEmail);
				Assert.IsTrue(actual);
			}
		}


		[TestMethod()]
		public void AddPresenter_ValidCoPresenterInvalidSession_ReturnsTrue()
		{
			string coPresenterEmail;
			int sessionID = -1;
			using (var context = new CodeCampEntities())
			{
				coPresenterEmail = context.aspnet_Membership.First().Email;
			}

			using (TransactionScope tran = new TransactionScope())
			{
				bool actual = CodeCampBL.AddPresenter(sessionID, coPresenterEmail);
				Assert.IsFalse(actual);
			}
		}


		/// <summary>
		///A test for SaveSessionAttachment
		///</summary>
		[TestMethod()]
		[ExpectedException(typeof(InvalidOperationException))]
		public void SaveSessionAttachment_MismatchedPresenterAndSession_Throws()
		{
			HttpPostedFileBase uploaded = null;
			Guid userId = new Guid();
			int sessionID = 0;
			CodeCampBL.SaveSessionAttachment(uploaded, userId, sessionID);
		}

		[TestMethod()]
		[ExpectedException(typeof(NullReferenceException))]
		public void SaveSessionAttachment_ValidPresenterAndSession_Throws()
		{
			Session session;
			HttpPostedFileBase uploaded = null;
			Guid userId = new Guid();
			int sessionID = 0;

			using (var context = new CodeCampEntities())
			{
				session = context.Sessions.Include("Speakers").First(x => x.Speakers.Count > 0);
			}
			userId = session.Speakers.First().UserId;
			sessionID = session.SessionID;

			// throws null exceptoin because of non mocked httppostedfilebase
			CodeCampBL.SaveSessionAttachment(uploaded, userId, sessionID);
		}

		/// <summary>
		///A test for SaveTags
		///</summary>
		[TestMethod()]
		public void SaveTags_NewTags_Saves()
		{
			using (var scope = new TransactionScope())
			{

				var context = new CodeCampEntities();

				var session = context.Sessions.Include("Speakers").First(x => x.Speakers.Count > 0);
				Assert.IsNotNull(session);
				Guid userId = session.Speakers.First().UserId;
				int sessionID = session.SessionID;


				var tags = new string[] { "Hello", "World" };
				CodeCampBL.SaveTags(sessionID, tags, userId);

				var actual = context.Sessions.Include("Tags").First(s => s.SessionID == sessionID).Tags.ToList();
				Assert.IsNotNull(actual);
				Assert.AreEqual(tags.Length, actual.Count);
			}
		}


		/// <summary>
		///A test for SaveTags
		///</summary>
		[TestMethod()]
		public void SaveTags_ExistingTagsDifferentCapitalization_ReusesExisting()
		{
			using (var scope = new TransactionScope())
			{

				string testTag = "CaseDoesNotMatter";
				var context = new CodeCampEntities();
				// ensure doesn't already exist
				Assert.IsTrue(!context.Tags.Any(t => t.Name == testTag));

				var session = context.Sessions
					.Include("Tags").Include("Speakers").First(x => x.Tags.Count > 0);
				Assert.IsNotNull(session);
				Guid userId = session.Speakers.First().UserId;
				int sessionID = session.SessionID;


				var tags = new[] { testTag };
				CodeCampBL.SaveTags(sessionID, tags, userId);

				var actual = context.Tags.First(t => t.Name == testTag);

				Assert.IsNotNull(actual);

				tags = new[] { testTag.ToLower() };

				CodeCampBL.SaveTags(sessionID, tags, userId);

				var actual2 = context.Tags.Where(t => t.Name == testTag.ToLower() || t.Name == testTag).ToList();

				Assert.AreEqual(1, actual2.Count);

			}
		}

		/// <summary>
		///A test for SessoinInterest
		///</summary>
		[TestMethod()]
		public void SessoinInterest_CurrentCamp_ContainsValues()
		{
			Dictionary<string, int> actual;
			actual = CodeCampBL.SessoinInterest();
			Assert.IsNotNull(actual);
			Assert.IsTrue(actual.Keys.Count > 0);
		}


		[TestMethod()]
		public void TagUsage_CurrentCamp_ContainsValues()
		{
			Dictionary<string, int> actual;
			actual = CodeCampBL.TagUsage();
			Assert.IsNotNull(actual);
			Assert.IsTrue(actual.Keys.Count > 0);
		}

		/// <summary>
		///A test for AddSession
		///</summary>
		[TestMethod()]
		public void AddSession_ValidData_ReturnsNewSessionID()
		{

			Guid userId = (new CodeCampEntities()).MemberProfiles.First(m => m.AllowPublicProfile).UserId;

			using (TransactionScope scope = new TransactionScope())
			{
				Session session = new Session()
									{
										Description = "Desc in breif",
										Name = "Name of session",
										Excerpt = "In short ...",
										SegmentCount = 1
									};

				int actual = CodeCampBL.AddSession(session, userId);
				Assert.IsTrue(actual > 0);
			}
		}


		[TestMethod()]
		public void ListByTrack_CurrentCamp_ReturnsValues()
		{
			Dictionary<string, List<SessionDetail>> actual;
			actual = CodeCampBL.ListByTrack(null, "Unassigned");
			Assert.IsNotNull(actual);
			// since the "Unassigned" track will catch any non-tracked sessions, 
			// at least 1 item should be there.
			Assert.IsTrue(actual.Count > 1);
		}

		[TestMethod()]
		public void ListByTrack__AllSessionsAccountedFor()
		{
			int sessioncount = CodeCampBL.ListSessions().Count();
			Dictionary<string, List<SessionDetail>> actual;
			actual = CodeCampBL.ListByTrack(null, "Unassigned");
			Assert.IsNotNull(actual);
			Assert.AreEqual(sessioncount, actual.Sum(kvp => kvp.Value.Count));
		}
	}
}
